<?php

define('OPERATOR_PREF', 'operator_');

function _is_a($o, $class_name)
{
    if (_is_system($class_name)) {
        $function = 'is_' . _get_type($class_name);
        return $function($o);
    } else {
        return is_a($o, _get_type($class_name));
    }
}

function get_ancestor_or_self_classes($o, $master=null, $inclusive=true)
{
    if (is_object($o)) {
        $class = get_class($o);
    } elseif (is_string($o)) {
        $class = $o;
    } else {
        throw new Exception();
    }
    if (! class_exists($class)) {
        throw new Exception();
    }
    if (! is_null($master) && ! class_exists($master)) {
        throw new Exception();
    }

    $ancestor_or_self = array($class);
    while ($parent = get_parent_class($class)) {
        if ((! is_null($master)) && ($parent == $master)) {
            if ($inclusive) {
                $ancestor_or_self[] = $parent;
            }
            break;
        }
        $ancestor_or_self[] = $parent;
        $class = $parent;
    }
    return $ancestor_or_self;
}

function get_ancestor_classes($o)
{
    if (is_object($o)) {
        $class = get_class($o);
    } elseif (is_string($o)) {
        $class = $o;
    } else {
        throw new Exception();
    }
    if (! class_exists($class)) {
        throw new Exception();
    }

    $ancestor_or_self = array();
    while ($parent = get_parent_class($class)) {
        $hierarhy1[] = $parent;
        $class = $parent;
    }
    return $ancestor_or_self;
}

function _is_system($class_name)
{
    if (strpos($class_name, '#') === 0) {

        switch (substr($class_name, 1)) {

            case 'int':
            case 'integer':
            case 'bool':
            case 'string':
            case 'float':
                return true;
                break;

            default:
                throw "Xernya, rebyata!";
        }
    } else {
        return false;
    }
}

function _get_type($class_name)
{
    if (_is_system($class_name)) {
        return substr($class_name, 1);
    } else {
        if (class_exists($class_name)) {
            return $class_name;
        } else {
            throw "Xernya, rebyata!";
        }
    }
}

function add($o, $value)
{
    $method = OPERATOR_PREF.'add';
    if (is_object($o) && method_exists($o, $method)) {
        return $o->$method($value);
    } else {
        return $o + $value;
    }
}

function sub($o, $value)
{
    $method = OPERATOR_PREF.'sub';
    if (is_object($o) && method_exists($o, $method)) {
        return $o->$method($value);
    } else {
        return $o - $value;
    }
}

function pref_inc()
{
    $num_arg = func_num_args();
    $method = OPERATOR_PREF.'pref_inc';
    if ($num_arg == 1) {
        $o = func_get_arg(0);
        if (is_object($o) && method_exists($o, $method)) {
            return $o->$method();
        } else {
            return ++$o;
        }
    } else {
        throw "Xernya, rebyata!";
    }
}

function pref_dec()
{
    $num_arg = func_num_args();
    $method = OPERATOR_PREF.'pref_dec';
    if ($num_arg == 1) {
        $o = func_get_arg(0);
        if (is_object($o) && method_exists($o, $method)) {
            return $o->$method();
        } else {
            return --$o;
        }
    } else {
        throw "Xernya, rebyata!";
    }
}

function inc()
{
    $num_arg = func_num_args();
    $method = OPERATOR_PREF.'inc';
    if ($num_arg == 1) {
        $o = func_get_arg(0);
        if (is_object($o) && method_exists($o, $method)) {
            return $o->$method();
        } else {
            return $o++;
        }
    } elseif($num_arg == 2) {
        $o = func_get_arg(0);
        $num = func_get_arg(1);
        if (is_object($o) && method_exists($o, $method)) {
            return $o->$method($num);
        } else {
            return $o += $num;
        }
    } else {
        throw "Xernya, rebyata!";
    }
}

function dec()
{
    $num_arg = func_num_args();
    $method = OPERATOR_PREF.'dec';
    if ($num_arg == 1) {
        $o = func_get_arg(0);
        if (is_object($o) && method_exists($o, $method)) {
            return $o->$method();
        } else {
            return $o--;
        }
    } elseif($num_arg == 2) {
        $o = func_get_arg(0);
        $num = func_get_arg(1);
        if (is_object($o) && method_exists($o, $method)) {
            return $o->$method($num);
        } else {
            return $o -= $num;
        }
    } else {
        throw "Xernya, rebyata!";
    }
}

function eq($value1, $value2)
{
    if (is_object($value1) && method_exists($value1, 'eq')) {
        return $value1->eq($value2);
    } elseif(is_object($value2) && method_exists($value2, 'eq')) {
        return $value2->eq($value1);
    } else {
        return $value1 == $value2;
    }
}

function ne($value1, $value2)
{
    if (is_object($value1) && method_exists($value1, 'ne')) {
        return $value1->ne($value2);
    } elseif(is_object($value2) && method_exists($value2, 'ne')) {
        return $value2->ne($value1);
    } else {
        return $value1 != $value2;
    }
}

function gt($value1, $value2)
{
    if (is_object($value1) && method_exists($value1, 'gt')) {
        return $value1->gt($value2);
    } else {
        return $value1 > $value2;
    }
}

function lt($value1, $value2)
{
    if (is_object($value1) && method_exists($value1, 'lt')) {
        return $value1->lt($value2);
    } else {
        return $value1 < $value2;
    }
}

function ge($value1, $value2)
{
    if (is_object($value1) && method_exists($value1, 'ge')) {
        return $value1->ge($value2);
    } else {
        return $value1 >= $value2;
    }
}

function le($value1, $value2)
{
    if (is_object($value1) && method_exists($value1, 'le')) {
        return $value1->le($value2);
    } else {
        return $value1 <= $value2;
    }
}

?>